/*
 *  Copyright (C) 2004 Cidero, Inc.
 *
 *  Permission is hereby granted to any person obtaining a copy of 
 *  this software to use, copy, modify, merge, publish, and distribute
 *  the software for any non-commercial purpose, subject to the
 *  following conditions:
 *  
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 
 *  OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
 *  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY IN CONNECTION WITH THE SOFTWARE.
 * 
 *  File: $RCSfile: SynchronizedQueue.java,v $
 *
 */

package com.cidero.util;

import java.util.LinkedList;

public class SynchronizedQueue 
{
  int maxSize = -1;  // unbounded
  LinkedList queue = new LinkedList();
  
  public SynchronizedQueue()
  {
  }
  public SynchronizedQueue( int maxSize )
  {
    this.maxSize = maxSize;
  }

  /**
   *  add
   *  @param timeoutMillisec - time to wait in milliseconds. if timeout is
   *  0, wait forever 
   *
   *  @return  true if object added to list, false if not
   *  
   */
  public synchronized boolean add( Object obj, long timeoutMillisec )
  {
    if( (maxSize > 0) && (queue.size() >= maxSize ) )
    {
      try
      {
        wait( timeoutMillisec );
      }
      catch( InterruptedException e )
      {
        // Ignore for now
        return false;
      }

      // If queue still full, logic error somewhere...
      if( queue.size() >= maxSize )
      {
        System.out.println("WorkQueue: add() woke up but queue still full");
        return false;
      }
    }
    
    queue.addLast( obj );
    notify();
    return true;
    
  }

  /**
   *  get object from queue
   *
   *  @param timeoutMillisec - time to wait in milliseconds. if timeout is
   *  0, wait forever 
   *
   *  @return  object, or null if timeout
   *  
   */
  public synchronized Object get( long timeoutMillisec )
  {
    if( queue.isEmpty() )
    {
      try
      {
        wait( timeoutMillisec );
      }
      
      catch( InterruptedException e )
      {
        // Ignore for now
      }

      if( queue.isEmpty() )
        return null;
    }
    
    Object obj = queue.removeFirst();

    notify();   // Notify sender side that more queue space is now available

    return obj;
  }

  public synchronized boolean isEmpty()
  {
    return queue.isEmpty();
  }

}

